package com.gitee.dolt.log.aspect;

import java.util.Arrays;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;

import cn.hutool.core.date.DateUtil;
import com.gitee.dolt.utils.EnvUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Profile;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
@Profile({EnvUtils.DEV, EnvUtils.TEST})
@Slf4j
public class ActionLoggingAspect {
    private static int maxOutputLengthOfParaValue = 512;

    public ActionLoggingAspect() {
    }

    @Pointcut("within(@org.springframework.stereotype.Controller *) || within(@org.springframework.web.bind.annotation.RestController *)")
    public void actionLoggingPointcut() {
    }

    @Around("actionLoggingPointcut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        if (!log.isDebugEnabled()) {
            return joinPoint.proceed();
        }
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        Signature signature = joinPoint.getSignature();
        StringBuilder sb = (new StringBuilder("\nStringBoot action report -------- ")).append(DateUtil.now()).append(" --------------------------\n");
        sb.append("Url         : ").append(request.getMethod()).append(" ").append(request.getRequestURI()).append("\n");
        sb.append("Controller  : ").append(signature.getDeclaringTypeName()).append(".(").append(signature.getDeclaringType().getSimpleName()).append(".java:1)\n");
        sb.append("Method      : ").append(signature.getName()).append("\n");
        sb.append("Args        : ").append(Arrays.toString(joinPoint.getArgs())).append("\n");
        Enumeration<String> e = request.getParameterNames();
        if (e.hasMoreElements()) {
            sb.append("Parameter   : ");

            for (; e.hasMoreElements(); sb.append("  ")) {
                String name = e.nextElement();
                String[] values = request.getParameterValues(name);
                if (values.length == 1) {
                    sb.append(name).append("=");
                    if (values[0] != null && values[0].length() > maxOutputLengthOfParaValue) {
                        sb.append(values[0], 0, maxOutputLengthOfParaValue).append("...");
                    } else {
                        sb.append(values[0]);
                    }
                } else {
                    sb.append(name).append("[]={");

                    for (int i = 0; i < values.length; ++i) {
                        if (i > 0) {
                            sb.append(",");
                        }
                        sb.append(values[i]);
                    }

                    sb.append("}");
                }
            }

            sb.append("\n");
        }

        sb.append("--------------------------------------------------------------------------------\n");
        log.debug(sb.toString());
        return joinPoint.proceed();
    }
}
